/* eslint-disable @typescript-eslint/no-empty-function */
/* eslint-disable @typescript-eslint/no-explicit-any */
import type {Ref} from 'vue';
import {ref, watch, unref} from 'vue';
import {useThrottleFn, useDebounceFn} from '@vueuse/core';

export type RemoveEventFn = () => void;

export interface UseEventParams {
    el?: Element | Ref<Element | undefined> | Window | any;
    name: string;
    listener: EventListener;
    options?: boolean | AddEventListenerOptions;
    autoRemove?: boolean;
    isDebounce?: boolean;
    wait?: number;
}

// 节点添加事件 默认节点为window
// 函数返回一个对象 removeEvent 为无返回值的function
export function useEventListener({el = window, name, listener, options, autoRemove = true, isDebounce = true, wait = 80,}: UseEventParams): { removeEvent: RemoveEventFn } {

    let remove: RemoveEventFn = () => {};
    const isAddRef = ref<boolean>(false); //

    if (el) {

        const element = ref(el as Element) as Ref<Element>;
        // console.log('el',element.value)
        const handler = isDebounce ? useDebounceFn(listener, wait) : useThrottleFn(listener, wait); // 是否使用防抖函数？ 防抖：节流

        const realHandler = wait ? handler : listener; // wait 延迟时间如果设置则使用防抖节流函数 否则使用原函数

        // 移除节点方法
        const removeEventListener = (e: Element) => {
            isAddRef.value = true;
            e.removeEventListener(name, realHandler, options);
        };
        // 添加节点方法
        const addEventListener = (e: Element) => e.addEventListener(name, realHandler, options);

        // 当前节点添加的方法被移除的监听事件 被移除后触发
        const removeWatch = watch(
            element,
            (v, _ov, cleanUp) => {
                if (v) {
                    !unref(isAddRef) && addEventListener(v);
                    cleanUp(() => {
                        autoRemove && removeEventListener(v);
                    });
                }
            },
            {immediate: true},
        );

        remove = () => {
            removeEventListener(element.value);
            removeWatch();
        };
    }
    return {removeEvent: remove};
}
